/*
// 生成验证码画布
参数:
options: {
  depositId: string   //存放验证码画布的元素ID       必填
  width: number       //验证码画布宽                选填,100px
  height: number      //验证码画布高                选填,40px
  len: number         //验证码长度                  选填,默认为6位长度验证码
  color: string       //验证码颜色                  选填,默认为随机生成
  bgColor: string     //验证码画布背景色            选填,默认为随机生成
  lineBln: boolean    //是否开启干扰线              选填,默认为不开启
  dotBln: boolean     //是否开启干扰点              选填,默认为不开启
}
方法:
.confirmCode(code);  // 校验验证码  code：string 待校验验证码   return true/false;
*/

//#region    依赖函数
// 生成[0-9aA-zZ]数组
function _randomArr() {
    // 保存随机数组
    let randomArr = [];
    // 追加数字
    for (let i = 0; i < 10; i++) {
        randomArr.push(i);
    }
    // 追加字母
    for (let i = 0; i < 26; i++) {
        randomArr.push(String.fromCharCode((65 + i)));
        randomArr.push((String.fromCharCode((65 + i))).toLocaleLowerCase());
    }
    return randomArr;
}

// 函数:生成一个随机数 min:最小值  max:最大值
function _randomNum(min, max) {
    return Math.floor(Math.random() * (max - min) + min);
}

// 函数:生成一个随机rgb色 min:最小值  max:最大值
function _randomColor(min, max) {
    let r = _randomNum(min, max);
    let g = _randomNum(min, max);
    let b = _randomNum(min, max);
    return "rgb(" + r + "," + g + "," + b + ")";
}
//#endregion

//#region 生成验证码画布主函数
// 验证码构造函数
let VerificationCode = function(options) {
    if (!options.depositId) return;
    // 默认参数
    let initParams = {
        depositId: "",
        width: 100,
        height: 40,
        len: 6,
        color: "random",
        bgColor: "random",
        lineBln: false,
        dotBln: false
    };
    // 合并参数
    options = Object.assign(initParams, options);
    // 初始化
    this._init(options);
    // 绑定事件
    this._bind();
};

/* _init 初始化*/
VerificationCode.prototype._init = function({
    depositId,
    width,
    height,
    len,
    color,
    bgColor,
    lineBln,
    dotBln
}) {
    // 生成的验证码画布
    this.canvas = document.createElement("canvas");
    // 存放验证码画布的元素
    this.depositEle = document.getElementById(depositId);
    // 验证码画布宽
    this.width = width;
    // 验证码画布宽
    this.height = height;
    // 验证码长度
    this.len = len;
    // 验证码颜色
    this.color = color;
    // 验证码画布背景色
    this.bgColor = bgColor;
    // 是否开启干扰线
    this.lineBln = lineBln;
    // 是否开启干扰线
    this.dotBln = dotBln;
    // 保存生成验证码
    this.trueCode = [];
    // 初始生成验证码
    this._refresh(this.len);
};

/* _refresh 生成验证码 */
VerificationCode.prototype._refresh = function(len) {
    // 获取验证码画布
    let canvas = this.canvas;
    // 设置画布绘制类型
    let ctx = canvas.getContext("2d");
    // 设置画布的宽高
    canvas.width = this.width;
    canvas.height = this.height;
    // 设置画布文本垂直居中
    ctx.textBaseline = "middle";
    // 设置画布背景色
    let bgColor = this.bgColor != "random" ? this.bgColor : _randomColor(0, 255);
    ctx.fillStyle = bgColor;
    // 设置画布矩形
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    // 获取数字字母数组
    let randomArr = _randomArr();
    // 生成对应长度的验证码,并绘制到canvas上
    for (let i = 0; i < len; i++) {
        // 随机生成一个字母或数字
        let randomNum = randomArr[_randomNum(0, randomArr.length)];
        // 把生成的每个字母或数字放在生成数组中
        this.trueCode[i] = randomNum;
        // 随机生成字体大小
        let maxFontSize = parseInt(canvas.width / len);
        let minFontSize = maxFontSize - 5;
        let font = _randomNum(minFontSize, maxFontSize) + "px PingFang SC,Microsoft YaHei";
        ctx.font = font;
        // 设置字体颜色
        let color = this.color != "random" ? this.color : _randomColor(0, 255);
        ctx.fillStyle = color;
        // 设置字体阴影
        ctx.shadowOffsetX = _randomNum(-3, 3);
        ctx.shadowOffsetY = _randomNum(-3, 3);
        ctx.shadowBlur = _randomNum(-3, 3);
        ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
        // 获取每个字体的坐标
        let x = (canvas.width - 10) / len * i + 10;
        let y = canvas.height / 2;
        // 随机生成选择角度
        let deg = _randomNum(-30, 30);
        // 设置旋转角度和坐标原点
        ctx.translate(x, y);
        ctx.rotate((deg * Math.PI) / 180);
        // 绘画文本
        ctx.fillText(randomNum, 0, 0);
        // 恢复旋转角度和坐标原点
        ctx.rotate((-deg * Math.PI) / 180);
        ctx.translate(-x, -y);
    };
    // 绘制干扰线
    if (this.lineBln) {
        for (let i = 0; i < 4; i++) {
            // 开始一条路径
            ctx.beginPath();
            // 随机生成颜色
            ctx.strokeStyle = _randomColor(0, 255);
            // 绘制起点 x轴随机生成,y轴随机生成
            ctx.moveTo(_randomNum(0, canvas.width), _randomNum(0, canvas.height));
            // 绘制终点 x轴随机生成，y轴随机生成
            ctx.lineTo(_randomNum(0, canvas.width), _randomNum(0, canvas.height));
            // 进行绘制
            ctx.stroke();
        }
    };
    // 绘制干扰点
    if (this.dotBln) {
        for (let i = 0; i < canvas.width / 4; i++) {
            // 随机生成x坐标
            let x = _randomNum(0, canvas.width);
            // 随机生成y坐标
            let y = _randomNum(0, canvas.height);
            // 开始一条路径
            ctx.beginPath();
            // 创建干扰点
            ctx.arc(x, y, 1, 0, 2 * Math.PI);
            // 随机生成颜色
            ctx.fillStyle = _randomColor(0, 255);
            // 给路径填色
            ctx.fill();
        };
    };
    // 将验证码画布挂载到存放元素中
    this.depositEle.appendChild(this.canvas);
};

/*  _bind 绑定事件 */
VerificationCode.prototype._bind = function() {
    // 点击画布自动刷新
    this.canvas.addEventListener("click", () => {
        this._refresh(this.len);
    });
};

/* _confirmCode  校验方法 */
VerificationCode.prototype.confirmCode = function(code) {
    // 把验证码数组转换成小写的字符串
    var true_code = this.trueCode.join("").toLocaleLowerCase();
    // 把输入的验证码转为小写的字符串
    var input_code = code.toLocaleLowerCase();
    if (input_code === true_code) {
        return true;
    }
    return false;
};
//#endregion

// 导出方法
export default VerificationCode;